package com.djh.security.config;

import com.djh.security.handle.AuthExceptionEntryPoint;
import com.djh.security.handle.CustomAccessDeniedHandler;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;

import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * spring security配置
 * <p>在WebSecurityConfigurerAdapter不拦截oauth要开放的资源
 *
 * @author qipp
 * @date 2020/1/10 22:37
 * @since 1.0.1
 */
@ConditionalOnBean(WebClientConfig.class)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 角色/权限 分隔符{@value}
     */
    private final static String TO = "2";

    /**
     * 无需授权即可访问的接口{@value}
     */
    private final static String UN_AUTHENTICATED = "unAuthenticated";

    /**
     * 指定角色{@value}
     */
    private final static String ROLE = "role";

    /**
     * 指定权限{@value}
     */
    private final static String AUTH = "auth";

    /**
     * 权限不足处理器
     */
    private final CustomAccessDeniedHandler customAccessDeniedHandler;

    /**
     * 注入配置的tokenStore
     */

    /**
     * 用来解决匿名用户访问无权限资源时的异常
     */
    private final AuthExceptionEntryPoint authExceptionEntryPoint;






    private final SecurityProperties properties;

    public WebSecurityConfig(CustomAccessDeniedHandler customAccessDeniedHandler, AuthExceptionEntryPoint authExceptionEntryPoint, SecurityProperties properties) {
        this.customAccessDeniedHandler = customAccessDeniedHandler;
        this.authExceptionEntryPoint = authExceptionEntryPoint;
        this.properties = properties;
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);

        // 设置不受保护路径 设置受保护路径需要的角色权限（某司姓老师贡献的）
        Map<String, List<String>> antMatchers = properties.getAntMatchers();
        if (antMatchers != null) {
            Set<String> keys = antMatchers.keySet();
            for (String key : keys) {
                if (key.equals(UN_AUTHENTICATED)) {
                    List<String> urls = antMatchers.get(key);
                    for (String url : urls) {
                        http.authorizeRequests().antMatchers(url).permitAll();
                    }
                }else{
                    String type = key.split(TO)[0];
                    String str = key.split(TO)[1];
                    List<String> urls = antMatchers.get(key);
                    if (type.equals(ROLE)) {
                        for (String url : urls) {
                            http.authorizeRequests().antMatchers(url).hasRole(str);
                        }
                    }
                    if (type.equals(AUTH)) {
                        for (String url : urls) {
                            http.authorizeRequests().antMatchers(url).hasAuthority(str);
                        }
                    }
                }
            }
        }

        // 配合测试的代码
        // /save/no不受保护
        // /user/save 受保护
        http.authorizeRequests()
                .antMatchers("/save/**").permitAll()
                .anyRequest().authenticated();

        // 权限不足处理器
        http.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler);
        http.oauth2Login();

    }

}
